<?php
/**
 * 游戏操作类
 * Created		: 2012-05-28
 * Modified		: 2012-07-07
 * @version		: 1.0.0
 * @author		: Joseph Chen (chenliq@gmail.com)
 */
class Game 
{
	/**
	 * 游戏表
	 * @var string
	 */
	public static $tbl = 'games';
	/**
	 * 游戏服务器表
	 * @var string
	 */
	public static $tbl_srv = 'game_server';
	/**
	 * 错误提示信息
	 * @var string
	 */
	public static $msg = '';
	/**
	 * 游戏接口密钥
	 * @var array
	 */
	public static $secretKey = array(
// 		'sxd'	=> '{the-test-api-key-for-s999}',
		'sxd'	=> '{0d5dc628-e03c-fa74-e9bb-bbaebe6c91c6}',
		'sssg'	=> 'bTfVZJP3OwMQkfnTMsAi',
		'yjdx'	=> 'ohPUBBxrm39SjL2wq21hlLpJhgR9KqeA',
		'lj'	=> 'long_591yo_pay_KEY_Kje9eIjeKEiirIi39i83LhjePk3K2kkjJ32KJw',
		'mhfx'	=> '38AB-E8C2-FCFC-3C68',
	);
	/**
	 * 部分游戏登录和充值KEY是分开的
	 * @var array
	 */
	public static $paySecretKey = array(
		'mhfx'	=> 'A778-1093-14B5-DA13'
	);
	/**
	 * 部分游戏有独立的tid（商户编号）参数
	 * @var array
	 */
	public static $apiTid = array(
		'yjdx'	=> 115,
		'lj'	=> '591yo',
	);
	
	/**
	 * 读取一个游戏信息
	 * @param int $gameId
	 */
	public static function read($gameId) 
	{
		// 游戏ID不能为非数字
		if (!ctype_digit((string)$gameId)) {
			return false;
		}
		$key = 'g:'.$gameId;
		$data = Cache::getHash($key);
		if (!$data) {
			$data = Db::read(self::$tbl, $gameId);
			Cache::setHash($key, $data);
		}
		return $data;
	}
	
	/**
	 * 获取游戏列表（条件可指定分类ID和首字母）
	 * @param int $cid 指定分类的ID
	 * @param char $letter
	 */
	public static function getGameList($cid=null, $letter=null) 
	{
		$gameIdList = array();
		$cidKey = 'gl-cid:'.$cid;
		$letterKey = 'gl-letter:'.$letter;
		$gameKey = 'g:';
		// 根据ID获取对应的游戏列表
		if (!is_null($cid)) {
			$gameIdList = Cache::sGetMembers($cidKey);
		}
		// 根据字母获取符合条件的游戏列表，并与前面条件的进行交集
		if (!is_null($letter)) {
			$tmp = Cache::sGetMembers($letterKey);
			$gameIdList = Cache::sInter($tmp, $gameIdList);
		}
		if ($gameIdList) {
			$list = array();
			foreach ($gameIdList as $gameId) {
				$list[] = self::read($gameId);
			}
		}
		// 无限制条件取所有游戏列表
		else if (is_null($cid) && is_null($letter)) {
			$gameIdList = Cache::lRange('gl', 0, -1);
			if ($gameIdList) {
				$list = array();
				foreach ($gameIdList as $gameId) {
					$list[] = self::read($gameId);
				}
			} else {
				$list = self::recacheAllGame();
			}
		} else {
			$list = array();
		}
		return $list;
	}
	
	/**
	 * 读取一个服务器信息
	 * @param int $serverId
	 */
	public static function readServer($serverId) 
	{
		// ID不能为非数字
		if (!ctype_digit((string)$serverId)) {
			return false;
		}
		$key = 'gs:'.$serverId;
		$data = Cache::getHash($key);
		if (!$data) {
			$data = Db::read(self::$tbl_srv, $serverId);
			Cache::setHash($key, $data, 86400);
		}
		return $data;
	}
	
	/**
	 * 获取指定游戏的服务器列表
	 * @param int $gameId
	 * @param int|null $status
	 */
	public static function getServerList($gameId=null, $status=null) 
	{
		if (is_null($gameId)) {
			$model = new Model('game_server');
			return $model->select();
		}
		$serverIdList = array();
		$serverIdList = Cache::sMembers('gsl:'.$gameId);
		if ($serverIdList) {
			$list = array();
			foreach ($serverIdList as $serverId) {
				$list[] = self::readServer($serverId);
			}
		} else {
			$list = self::recacheAllGameServer();
		}
		return $list;
	}
	
	/**
	 * 重新缓存所有游戏数据
	 */
	public static function recacheAllGame()
	{
		$model = new Model('games');
		$gameList = $model->select();
		$gcatModel = new Model('game_category');
		$catList = $gcatModel->select();
		$catList = Arr::simple($catList);
		// 先清空列表
		Cache::delete('gl');
		foreach ($gameList as $v) {
			$v['cname'] = $catList[$v['cid']];
			Cache::setHash('g:'.$v['id'], $v);
			Cache::rPush('gl', $v['id']);
			Cache::sAdd('gl-cid:'.$v['cid'], $v['id']);
			Cache::sAdd('gl-letter:'.$v['letter'], $v['id']);
		}
		
		return $gameList;
	}
	
	/**
	 * 重新缓存所有游戏服务器数据
	 */
	public static function recacheAllGameServer()
	{
		$model = new Model('game_server');
		$serverList = $model->select();
		foreach ($serverList as $v) {
			Cache::setHash('gs:'.$v['id'], $v);
			$key = 'gsl:'.$v['game_id'];
			Cache::sAdd($key, $v['id']);
			if ($v['recommend']) {
				$key = 'gsl-recommend:'.$v['game_id'];
				Cache::sAdd($key, $v['id']);
			}
		}
		return $serverList;
	}
	
	/**
	 * 检测一个账号在对应的游戏服务器是否有存在角色
	 * @param string $username
	 * @param int $serverId
	 * @return boolean
	 */
	public static function isRoleExist($username, $server, $game=null)
	{
		// 得到服务器信息
		if (is_array($server)) {
			$serverInfo = $server;
		} else {
			$serverInfo = self::readServer($server);
		}
		// 得到游戏信息
		if (is_array($game)) {
			$gameInfo = $game;
		} else {
			$gameInfo = self::read($serverInfo['game_id']);
		}
		$gameSign = $gameInfo['sign'];
		// 游戏联合运营的密钥
		$secretKey = self::$secretKey[$gameSign];
		// 假设不存在
		$result = false;
		// 当前时间戳
		$time = time();
		
		switch ($gameSign)
		{
			// 神仙道
			case 'sxd':
				$sign = md5($username.'_'.$serverInfo['domain'].'_'.$secretKey);
				$apiUrl = 'http://api.sxd.xd.com/api/check_user.php?user='.$username.'&domain='.$serverInfo['domain'].'&sign='.$sign;
				$return = Url::getContents($apiUrl);
				if ($return === '1') {
					$result = true;
				}
				break;
			// 梦幻飞仙
			case 'mhfx':
				$sign = md5($username.'_'.$serverInfo['domain'].'_'.$secretKey);
				$apiUrl = 'http://'.$serverInfo['domain'].'/api/cmn/active.php?account='.$username.'&serverid='.$serverInfo['sid'];
				$return = Url::getContents($apiUrl);
				if ($return > 0) {
					$result = true;
				}
				break;
			// 龙将
			case 'lj':
				$sign = md5($username.'_'.$serverInfo['domain'].'_'.$secretKey);
				$apiUrl = 'http://pay.my9yu.com/long/query/'.self::$apiTid['lj'].'/'.$serverInfo['sid'].'/by/username?name='.$username;
				$json = Url::getContents($apiUrl);
				$json = json_decode($json);
				if ($json->code === 0) {
					$result = true;
				}
				break;
			// 盛世三国
			case 'sssg':
				$sign = md5($username.'_'.$time.'_'.$secretKey);
				$apiUrl = 'http://'.$serverInfo['domain'].'/api/verify_user?user='.$username.'&time='.$time.'&sign='.$sign;
				$return = Url::getContents($apiUrl);
				if ($return === '1') {
					$result = true;
				} else if ($return === '2') {
					$result = 2;
				}
				break;
			// 一骑当先
			case 'yjdx':
				$sid = $serverInfo['sid'];
				$auth = base64_encode('tid='.self::$apiTid[$gameSign].'&sid='.$sid.'&account='.$username.'&time='.$time);
				$verify = md5($auth.$secretKey);
				$apiUrl = 'http://up.9787.com/api/1/uinterface.php?action=checkrole&auth='.$auth.'&verify='.$verify;
				$json = Url::getContents($apiUrl);
				$return = json_decode($json);
				if ($return->result == 1) {
					$result = true;
				}
				break;
			
			default:
				$result = false;
				break;
		}
		return $result;
	}
	
	/**
	 * 获取游戏角色信息
	 * @param string $username
	 * @param int $serverId
	 * @return array
	 */
	public static function getRoleInfo($username, $server, $game=null)
	{
		// 得到服务器信息
		if (is_array($server)) {
			$serverInfo = $server;
		} else {
			$serverInfo = self::readServer($server);
		}
		// 得到游戏信息
		if (is_array($game)) {
			$gameInfo = $game;
		} else {
			$gameInfo = self::read($serverInfo['game_id']);
		}
		$gameSign = $gameInfo['sign'];
		// 游戏联合运营的密钥
		$secretKey = self::$secretKey[$gameSign];
		// 当前时间戳
		$time = time();
		
		switch ($gameSign)
		{
			// 神仙道
			case 'sxd':
				$sign = md5($username.'_'.$serverInfo['domain'].'_'.$secretKey);
				$apiUrl = 'http://api.sxd.xd.com/api/user.php?user='.$username.'&domain='.$serverInfo['domain'].'&sign='.$sign;
				$json = Url::getContents($apiUrl);
				$result = json_decode($json, true);
				if (!is_array($result)) {
					$roleInfo = $json;
					break;
				}
				$roleInfo = array(
					'name'			=> $result['nickname'],
					'level'			=> $result['player_level'],
					'exp'			=> $result['player_exp'],
					'create_time'	=> $result['create_time'],
					'offline_time'	=> $result['last_offline_time'],
					'ingot'			=> $result['ingot'],
					'vip'			=> $result['vip'],
					'mission_lock'	=> $result['mission_lock'],
				);
				break;
			// 梦幻飞仙
			case 'mhfx':
				$sign = md5($username.$serverInfo['sid'].$secretKey);
				$apiUrl = 'http://'.$serverInfo['domain'].'/api/cmn/role_info.php?account='.$username.'&serverid='.$serverInfo['sid'].'&sign='.$sign.'&json=1';
				$json = Url::getContents($apiUrl);
				$result = json_decode($json, true);
				if (!is_array($result)) {
					$roleInfo = $json;
					break;
				}
				// 取角色等级最高的角色
				$maxLvl = 0;
				$tmp = null;
				foreach ($result as $v) {
					if ($v['lev'] > $maxLvl) {
						$tmp = $v;
					}
				}
				if (!$tmp) {
					$result = $result[0];
				} else {
					$result = $tmp;
				}
				$roleInfo = array(
					'name'			=> urldecode($result['nickname']),
					'level'			=> $result['lev'],
					'online'		=> $result['online'],
				);
				break;
			// 龙将
			case 'lj':
				$roleInfo = array();
				break;
			// 盛世三国
			case 'sssg':
				$select = 'name,level,exp,createtime,offlinetime';
				$sign = md5('get_player_info_'.$time.'_'.$secretKey);
				$apiUrl = 'http://'.$serverInfo['domain'].'/api/player?users='.$username.'&select='.$select.'&time='.$time.'&sign='.$sign;
				$json = Url::getContents($apiUrl);
				$result = json_decode($json, true);
				if (!is_array($result)) {
					$roleInfo = $json;
					break;
				}
				$result = $result[$username];
				$roleInfo = array(
					'name'			=> $result['name'],
					'level'			=> $result['level'],
					'exp'			=> $result['exp'],
					'create_time'	=> $result['createtime'],
					'offline_time'	=> $result['offlinetime'],
				);
				break;
			// 一骑当先
			case 'yjdx':
				$sid = $serverInfo['sid'];
				$auth = base64_encode('tid='.self::$apiTid[$gameSign].'&sid='.$sid.'&accounts='.$username.'&time='.$time);
				$verify = md5($auth.$secretKey);
				$apiUrl = 'http://up.9787.com/api/1/uinterface.php?action=getRoleInfo&auth='.$auth.'&verify='.$verify;
				$json = Url::getContents($apiUrl);
				$result = json_decode($json, true);
				if (!is_array($result)) {
					$roleInfo = $json;
					break;
				}
				if (isset($result['result'])) {
					return $result;
				}
				$result = $result[0];
				$roleInfo = array(
					'name'			=> $result['name'],
					'level'			=> $result['officium'],
					'exp'			=> $result['prestige'],
					'create_time'	=> substr($result['active_time'], 0, 10),
					'offline_time'	=> substr($result['last_heartbeat'], 0, 10),
					'vip'			=> $result['vip_level'],
				);
				break;
			
			default:
				$roleInfo = array();
			break;
		}
		return $roleInfo;
	}
	
	/**
	 * 生成新手卡
	 * @param string $username
	 * @param int $serverId
	 * @return array
	 */
	public static function generateNewbieCard($username, $serverId)
	{
		$serverInfo = self::readServer($serverId);
		$gameInfo = self::read($serverInfo['game_id']);
		$gameSign = $gameInfo['sign'];
		// 游戏联合运营的密钥
		$secretKey = self::$secretKey[$gameSign];
		// 当前时间戳
		$time = time();
	
		switch ($gameSign)
		{
			// 神仙道
			case 'sxd':
				return md5($username.$serverInfo['domain']);
				break;
			// 梦幻飞仙
			case 'mhfx':
				return md5($secretKey.$username);
				break;
			// 龙将
			case 'lj':
				return md5('long'.self::$apiTid['lj'].$serverInfo['sid'].$username);
				break;
			// 盛世三国
			case 'sssg':
				$data = array(
					'user'		=> $username,
					'card_id'	=> 1,
					'time'		=> $time,
					'server_id'	=> $serverId,
					'auto'		=> 1,
					'num'		=> 1,
					'max_num'	=> 1,
					'limit_time'=> 0
				);
				$data['sign'] = md5(join('_', $data).'_'.$secretKey);
				$url = 'http://'.$serverInfo['domain'].'/api/card';
				$json = Url::post($url, $data);
				$code = json_decode($json);
				if (!is_array($code)) {
					return '';
				}
				return $code[0];
				break;
			// 一骑当先
			case 'yjdx':
				return md5($username.$serverInfo['domain']);
				break;
	
			default:
				return '';
			break;
		}
		return '';
	}
	
	/**
	 * 充值到游戏中去
	 */
	public static function pay($orderData)
	{
		$gameInfo = self::read($orderData['game_id']);
		$serverInfo = self::readServer($orderData['server_id']);
		$gameSign = substr($gameInfo['domain'], 0, strpos($gameInfo['domain'], '.'));
		$server_url = 'http://'.$serverInfo['domain'];
		$sign = substr($serverInfo['domain'], 0, strpos($serverInfo['domain'], '.'));
		// 充值人民币金额(默认单位:元)
		$money = $orderData['fact_value']/$gameInfo['pay_rate'];
		// 充值金额转成游戏币
		// 充值金额为平台币,转成RMB,再乘以游戏设置的RMB与游戏币的倍率
		$gold = floor($money * $gameInfo['pay_rate']);
		// 游戏联合运营的密钥
		$secretKey = self::$secretKey[$gameSign];
	
		$user = $orderData['username'];
		$time = time();
		$order = $orderData['order_no'];
		$domain = $gameInfo['domain'];
		// 先假设充值失败
		$return = false;
		$curl = new Curl();
		// 测试时只有一个元宝
		$gold = 1;
		switch ($gameSign)
		{
			// 神仙道
			case 'sxd':
				$sign   = md5($user.'_'.$gold.'_'.$order.'_'.$domain.'_'.$secretKey);
				$url = 'http://api.sxd.xd.com/api/buygold.php?user='.$user
						."&gold=".$gold."&order=".$order."&domain=".$domain."&sign=".$sign;
				self::$pay_game_status = Url::getContents($url);
				// 神仙道状态值为1或6,说明也充值成功了
				if (self::$pay_game_status === '1' || self::$pay_game_status === '6') {
					self::$pay_game_status = 1;
					$return = true;
				}
			break;
	
			// 盛世三国
			case 'sssg':
				$sign = md5($user.'_'.$time.'_'.$order.'_'.$gold.'_'.$secretKey) ;
				$url = $server_url."/api/charge?user=".$user."&gold=".$gold."&order=".$order."&time=".$time."&sign=".$sign;
				self::$pay_game_status = Url::getContents($url);
				if (self::$pay_game_status === '1') {
					$return = true;
				}
			break;
	
			// 一骑当先
			case 'yjdx':
				$sid = $serverInfo['sid'];
				$auth = base64_encode('tid='.self::$apiTid[$gameSign].'&sid='.$sid.'&account='.$user
						.'&oid='.$order.'&otype=0&money='.$money
						.'&gold='.$gold.'&ip='.$_SERVER['REMOTE_ADDR'].'&time='.$time);
				$verify = md5($auth.$secretKey);
				$url = "http://up.9787.com/api/1/uinterface.php?action=charge&auth=".$auth."&verify=".$verify;
				$json = Url::getContents($url);
				$res = json_decode($json, true);
				self::$pay_game_status = $res['result'];
				if (self::$pay_game_status === '1') {
					$return = true;
				}
			break;
	
			// 龙将
			case 'lj':
				$sid = $serverInfo['sid'];
				$sign = md5($order.$secretKey);
				// 龙将金额单位为"分"
				$money = $money*100;
				$url = 'http://pay.my9yu.com/long/pay/591yo/'.$sid.'/by/username?name='.$user
				.'&money='.$money.'&gold='.$gold.'&coupon=0&coin=0&order='.$order.'&sign='.$sign;
				$json = Url::getContents($url);
				$res = json_decode($json, true);
				self::$pay_game_status = $res['code'];
				if (self::$pay_game_status == 0 || self::$pay_game_status == -5) {
					self::$pay_game_status = 1;
					$return  = true;
				}
			break;
	
			// 梦幻飞仙
			case 'mhfx':
				$secretKey = Games::$mhfxPayKey;
				$tmp = explode('.', $serverInfo['domain']);
				$sid = $tmp[0];
				$sign = strtolower(md5($user.$sid.$order.$money.$gold.$time.$secretKey)) ;
				$url = $server_url."/api/cmn/pay_sid.php?account=".$user
						."&serverid=".$sid."&coin=".$gold."&rmb=".$money
						."&orderid=".$order."&type=0"."&sign=".$sign."&time=".$time;
				$res = Url::getContents($url);
				if ($res === '1') {
					self::$pay_game_status = 1;
					$return  = true;
				} else if (false === $res) {
					self::$pay_game_status = 0;
				} else if (false === 'ERROR-15') {
					self::$pay_game_status = 1;
				} else {
					self::$pay_game_status = substr($res, 6);
				}
			break;
			
			// 未定义游戏接口,无法处理
			default:
				$return = false;
			break;
		  
		}
		return $return;
	}
	
}